package com.itfreer.gis.server;

import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.geotools.data.DataStoreFinder;
import org.geotools.data.postgis.PostgisNGDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.jdbc.JDBCDataStore;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import com.itfreer.gis.server.vector.FeatureDao;

/**
 * 定义基于PostGIS的处理器
 */
@Component
public class PostGISFeatureDao implements FeatureDao {

	@Value("${spring.datasource.url}")
	private String url;
	@Value("${spring.datasource.username}")
	private String username;
	@Value("${spring.datasource.password}")
	private String password;

	@Autowired
	protected JdbcTemplate jdbc;

	private JDBCDataStore dataStore;

	/**
	 * 获取指定切片下的要素
	 * 
	 * @param source 数据源
	 * @param extent 切片范围
	 * @return
	 * @throws @throws Exception
	 */
	@Override
	public List<Map<String, Object>> queryFeature(String source, String fields, String extent) {
		String sql = "select " + fields + "gid,st_astext(geom) as geom from " + source + " where "
				+ "st_intersects(geom, st_geomfromtext(?,4326)) ";
		List<Map<String, Object>> results = jdbc.queryForList(sql, extent);
		return results;
	}

	/**
	 * 获取所查询字段
	 * 
	 * @param source 数据源
	 * @return
	 * @throws Exception
	 */
	@Override
	public String fields(String source) throws Exception {
		SimpleFeatureSource featureSource = getFeatureSource(source);
		List<AttributeDescriptor> attrs = featureSource.getSchema().getAttributeDescriptors();
		String fields = "";
		for (AttributeDescriptor item : attrs) {
			String name = item.getName().toString();
			if (name.equals("shape_leng") || name.equals("shape_area") || name.equals("geom")) {
				continue;
			}
			fields += item.getName().toString() + ",";
		}
		return fields;
	}

	@Override
	public ReferencedEnvelope getBounds(String source) throws Exception {
		SimpleFeatureSource featureSource = getFeatureSource(source);
		ReferencedEnvelope bounds = featureSource.getBounds();
		return bounds;
	}

	@Override
	public CoordinateReferenceSystem getCoordinateReferenceSystem(String source) throws Exception {
		// 1、读取数据源
		SimpleFeatureSource featureSource = getFeatureSource(source);

		GeometryDescriptor geometryDescriptor = featureSource.getSchema().getGeometryDescriptor();
		CoordinateReferenceSystem sourceCrs = geometryDescriptor.getType().getCoordinateReferenceSystem();
		return sourceCrs;
	}

	/**
	 * 获取数据源
	 *
	 * @param source
	 * @return
	 * @throws SQLException
	 * @throws IOException
	 */
	private SimpleFeatureSource getFeatureSource(String source) throws SQLException, IOException {
		if (dataStore == null) {
			String urlCopy = url;
			urlCopy = urlCopy.replace("//", "").replace("/", ":");
			String[] msgs = urlCopy.split(":");
			Map<String, Object> params = new HashMap<>();
			params.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
			params.put(PostgisNGDataStoreFactory.HOST.key, msgs[2]);
			params.put(PostgisNGDataStoreFactory.PORT.key, msgs[3]);
			params.put(PostgisNGDataStoreFactory.DATABASE.key, msgs[4]);
			params.put(PostgisNGDataStoreFactory.SCHEMA.key, "public");
			params.put(PostgisNGDataStoreFactory.USER.key, username);
			params.put(PostgisNGDataStoreFactory.PASSWD.key, password);
			dataStore = (JDBCDataStore) DataStoreFinder.getDataStore(params);
		}
		return dataStore.getFeatureSource(source);
	}
}
